package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/pkg/errors"
)

const CALLINTERVAL int64 = 600

type AlarmCall struct {
	opt AlarmCallT
	dbo *DBOperation

	calledRid map[string]int64
	callChan  chan AlarmDataT
}

func NewAlarmcall(alarmCall *AlarmCallT, dbo *DBOperation) *AlarmCall {
	ac := AlarmCall{opt: *alarmCall, dbo: dbo}
	ac.calledRid = make(map[string]int64)
	ac.callChan = make(chan AlarmDataT)

	go ac.Run()

	return &ac
}

func (p *AlarmCall) Run() {
	var vType int
	var plate, text string
	var err error
	var t int
	var now time.Time
	var ok bool
	var calledTime int64

	for ac := range p.callChan {
		now = time.Now()

		if calledTime, ok = p.calledRid[ac.Rid]; ok {
			if now.Unix()-calledTime < CALLINTERVAL {
				continue
			}
		}

		t = now.Hour()*100 + now.Minute()
		for _, customer := range p.opt.Customers {
			if (customer.Tid != "" && p.dbo.teamHasReceiver(customer.Tid, ac.Rid)) ||
				(customer.Cid != 0 && p.dbo.companyHasReceiver(customer.Cid, ac.Rid)) {
				vType, plate, err = p.dbo.getVehicleInfo(ac.Rid)
				if err == nil {
					text = p.makeContent(vType, ac.CardId, ac.SN, plate, ac.WarnType)
					if text != "" {
						for _, s := range customer.Schedule {
							if t >= s.Start && t < s.End && s.Phone != "" {
								p.calledRid[ac.Rid] = now.Unix()

								go p.makeCall(s.Phone, text)
							}
						}
					}
				}
			}
		}
	}
}

func (p *AlarmCall) Close() {
	close(p.callChan)
}

func (p *AlarmCall) makeContent(vType, cardId, sn int, plate string, warnType int) string {
	delay := 1000
	warn := ""
	switch warnType {
	case 1:
		warn = "急漏气"
		break
	case 2:
		warn = "慢漏气"
		break
	case 3:
		warn = "温度高"
		break
	case 4:
		warn = "气压高"
		break
	case 5:
		warn = "气压低"
		break
	case 6:
		warn = "发射器失联"
		break
	case 7:
		warn = "发射器电池电压低"
		break
	}

	text := fmt.Sprintf("{%d},您好,车辆%s的%d卡%d号轮位发生%s故障，请及时处理。", delay, plate, cardId, sn, warn)
	return text
}

type CustomSoundT struct {
	FrameId int    `json:"frame_id"`
	Text    string `json:"sound_text"`
}
type CallT struct {
	TaskUuid    string         `json:"task_uuid"`
	Phone       string         `json:"called_num"`
	OrderTime   string         `json:"order_time"`
	CustomSound []CustomSoundT `json:"cust_sound"`
}

type CallResultT struct {
	Code  string `json:"code"`
	Error string `json:"error"`
}

func (p *AlarmCall) makeCall(phone, text string) error {
	var err error
	var res []byte

	defer func() {
		sErr := fmt.Sprintf(`给 %s 拨打电话:"%s"`, phone, text)
		if err != nil {
			sErr += ",失败：" + err.Error()
		} else {
			sErr += " 成功"
		}
	}()

	call := CallT{TaskUuid: p.opt.TaskUuid, Phone: phone, OrderTime: time.Now().Format("2006-01-02 15:04:05"),
		CustomSound: make([]CustomSoundT, 0)}
	cs := CustomSoundT{FrameId: p.opt.FrameId, Text: text}
	call.CustomSound = append(call.CustomSound, cs)

	buf, _ := json.Marshal(call)
	res, err = p.Post(p.opt.Host, "application/json", buf)

	if err != nil {
		return err
	}

	var callRes CallResultT
	err = json.Unmarshal(res, &callRes)
	if err != nil {
		return err
	}

	if callRes.Code != "200" {
		msg := callRes.Error
		if msg == "" {
			msg = "错误代码为" + callRes.Code
		}
		err = errors.New(msg)
	}

	return err
}

func (p *AlarmCall) Post(url string, contentType string, buf []byte) ([]byte, error) {
	resp, err := http.Post(url, contentType, bytes.NewReader(buf))
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	return body, nil
}
